package com.atguigu.tingshu.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.constant.RabbitConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.user.UserListenProcess;
import com.atguigu.tingshu.user.service.UserListenProcessService;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.atguigu.tingshu.vo.user.UserListenProcessVo;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserListenProcessServiceImpl implements UserListenProcessService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public BigDecimal getTrackBreakSecond(Long trackId) {
        //获取登录状态
        Long userId = AuthContextHolder.getUserId();
        //userId如果问空,则返回0,从头播放
        if (userId==null){
            return new BigDecimal(0);
        }
        //根据userId计算该用户的播放进度在哪个集合中
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);
        //通过userId和trackId查询播放进度
        UserListenProcess userListenProcess = this.mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId).and("trackId").is(trackId)),
                UserListenProcess.class, collectionName);
        if (userListenProcess==null){
            return new BigDecimal(0);
        }
        return userListenProcess.getBreakSecond();
    }

    @Override
    public void updateListenProcess(UserListenProcessVo processVo) {
        // 获取登录状态
        Long userId = AuthContextHolder.getUserId();
        // userId如果为空则直接结束，不需要保存播放进度
        if (userId == null){
            return;
        }
        // 根据userId计算该用户的播放进度保存在那个集合中
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);
        // userId和trackId查询播放进度
        UserListenProcess userListenProcess = this.mongoTemplate.findOne(Query
                        .query(Criteria.where("userId").is(userId).and("trackId").is(processVo.getTrackId())),
                UserListenProcess.class, collectionName);
        if (userListenProcess == null){
            // 新增播放进度
            userListenProcess = new UserListenProcess();
            BeanUtils.copyProperties(processVo, userListenProcess);
            userListenProcess.setId(IdWorker.getIdStr());
            userListenProcess.setUserId(userId);
            userListenProcess.setIsShow(1);
            userListenProcess.setCreateTime(new Date());
            userListenProcess.setUpdateTime(userListenProcess.getCreateTime());
        } {
            // 更新播放进度
            userListenProcess.setBreakSecond(processVo.getBreakSecond());
            userListenProcess.setUpdateTime(new Date());
        }
        this.mongoTemplate.save(userListenProcess, collectionName);

        // 保证四个一：同一个用户同一个声音同一天只统计一次
        Boolean flag = this.redisTemplate.opsForValue().getBit(RedisConstant.USER_LISTEN_PROCESS_PREFIX + userId, processVo.getTrackId());
        if (flag){
            return;
        }
        // 如果没有统计过则立马更新为已统计
        this.redisTemplate.opsForValue().setBit(RedisConstant.USER_LISTEN_PROCESS_PREFIX + userId, processVo.getTrackId(), true);
        // 设置为凌晨过期
        LocalDateTime endTime = LocalDateTime.of(LocalDate.now().plusDays(1), LocalTime.MIN);
        long seconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), endTime);
        this.redisTemplate.expire(RedisConstant.USER_LISTEN_PROCESS_PREFIX + userId, seconds, TimeUnit.SECONDS);

        // 发送消息，更新统计信息
        TrackStatMqVo statMqVo = new TrackStatMqVo();
        statMqVo.setAlbumId(processVo.getAlbumId());
        statMqVo.setTrackId(processVo.getTrackId());
        statMqVo.setBusinessNo(IdWorker.getIdStr());
        statMqVo.setStatType(SystemConstant.TRACK_STAT_PLAY);
        statMqVo.setCount(1);
        this.rabbitTemplate.convertAndSend(RabbitConstant.USER_EXCHANGE, RabbitConstant.TRACK_STAT_RK, JSON.toJSONString(statMqVo));
    }

    @Override
    public Map<String, Long> getLatelyTrack() {
        //获取登录状态
        Long userId = AuthContextHolder.getUserId();
        if (userId==null){
            //todo: 查询推广的声音,进行播放
            return null;
        }
        //计算用户的播放进度在哪个集合
        String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);
        //查询最近的播放进度
        UserListenProcess userListenProcess = this.mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId)).with(Sort.by(Sort.Order.desc("updateTime"))), UserListenProcess.class, collectionName);

        if (userListenProcess==null){
            //todo 查询推广的声音,进行播放
            return null;
        }
        HashMap<String,Long> map = new HashMap<>();
        map.put("trackId", userListenProcess.getTrackId());
        map.put("albumId", userListenProcess.getAlbumId());
        return map;
    }
}
